/**
 * 2017年12月28日
 */
package com.gitee.weixin.mp.handler.msg;

import com.gitee.weixin.mp.builder.TextBuilder;
import com.gitee.weixin.mp.handler.msg.text.AbstractTxTransaction;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.*;

/**
 * 接收到文本消息的处理器，匹配交易进行异步处理
 *
 * @author aaron 2017年12月28日
 */
@Component
public class TextMsgHandler extends AbstractWxMsgHandler {

    public static final int CORE_POOL_SIZE  = 5;
    public static final int QUEUE_CAPACITY  = 50;
    /**
     * 线程空闲10s后销毁（非核心线程）
     */
    public static final int KEEP_ALIVE_TIME = 10 * 1000;
    @Autowired
    ApplicationContext ac;

    Collection<AbstractTxTransaction> transactions;

    ExecutorService pool;

    @PostConstruct
    public void init() {
        transactions = ac.getBeansOfType(AbstractTxTransaction.class, false, false).values();
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("TextMsgHandler-pool-%d").build();
        this.pool = new ThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE * 10,
                                           KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
                                           new LinkedBlockingQueue<Runnable>(QUEUE_CAPACITY), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

    }

    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) {
        // 父类进行公共处理，存储消息等,返回null
        super.handle(wxMessage, context, wxMpService, sessionManager);

        // 获取session，从session中获取TxTransaction，优先使用已存在的会话
        WxSession session = sessionManager.getSession(wxMessage.getFromUser());
        AbstractTxTransaction transactionInSession = (AbstractTxTransaction) session.getAttribute(AbstractTxTransaction.SESSION_KEY_TXTRANSACTION);

        if (transactionInSession != null) {
            return doTransaction(wxMessage, context, wxMpService, sessionManager, transactionInSession);
        } else {
            String text = wxMessage.getContent();
            // 获取最合适的处理器(分数最高的)
            Optional<AbstractTxTransaction> transactionOpt = transactions.stream().filter(t -> t.matchScore(text) > 0)
                    .max((o1, o2) -> {
                        // 打分相等的话用前一个
                        return (o1.matchScore(text) >= o2.matchScore(text)) ? 1 : -1;
                    });
            if (transactionOpt.isPresent()) {
                return doTransaction(wxMessage, context, wxMpService, sessionManager, transactionOpt.get());
            }
        }
        //默认的处理逻辑
        String defaultContent = "收到您的TextMsg [" + wxMessage.getContent() + "]";
        return new TextBuilder().build(defaultContent, wxMessage, wxMpService);
    }

    private WxMpXmlOutMessage doTransaction(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager,
                                            AbstractTxTransaction txTransaction) {
        if (txTransaction.isAsyn()) {
            this.pool.submit(() -> {
                txTransaction.doTextTrans(wxMessage, context, wxMpService, sessionManager);
            });
            return null;
        } else {
            return txTransaction.doTextTrans(wxMessage, context, wxMpService, sessionManager);
        }
    }

}
